package com.turtle3d.user.grammars;

import com.turtle3d.App;
import com.turtle3d.formallanguage.grammar.Grammar;
import com.turtle3d.formallanguage.grammar.parser.SimpleParser;
import com.turtle3d.formallanguage.symbol.Method;
import com.turtle3d.formallanguage.symbol.Symbol;
import com.turtle3d.formallanguage.symbol.SymbolClass;
import com.turtle3d.formallanguage.symbol.SymbolFactory;
import com.turtle3d.util.Randomizer;

public class ChristmasTree extends Grammar
{
	
	public ChristmasTree(){
		
	}
	
	public void define(){														
		
		Method growthMethod = new Method(){
			public boolean calculate(Symbol removedSymbol, Symbol calculatedSymbol)
			{
				Float r = calculatedSymbol.getParameter("radius");
				Float r_mul = calculatedSymbol.getParameter("radiusMultiplier");
				calculatedSymbol.setParameter("radius", r*r_mul);
				
				Float d = calculatedSymbol.getParameter("distance");
				Float d_mul = calculatedSymbol.getParameter("distanceMultiplier");
				calculatedSymbol.setParameter("distance", d*d_mul+(calculatedSymbol.getParameter("distanceVariation")*d*Randomizer.getRandomizer().nextVariation()));
				
				return true;
				
			}
		};				
		
		Method angleMethod = new Method(){
			public boolean calculate(Symbol removedSymbol, Symbol calculatedSymbol)
			{
				float nIteration = calculatedSymbol.getBirthIteration()/(calculatedSymbol.getParameter("iterationsCount")-1f);
				//App.println(calculatedSymbol.getBirthIteration()+", "+calculatedSymbol.getParameter("iterationsCount"));
				calculatedSymbol.setParameter(Symbol.TURN_ANGLE, 90f*(1-nIteration));								
				//calculatedSymbol.setParameter(Symbol.TURN_ANGLE, 4f);				
				
				return true;
				
			}
		};
		
		SymbolClass branchB = new SymbolClass("B", "B(branch)");
		branchB.addMethod(new Method(){
			public boolean calculate(Symbol removedSymbol, Symbol calculatedSymbol)
			{
				
				calculatedSymbol.setParameter("distanceMultiplier", removedSymbol.getParameter("distanceMultiplierBranch"));				
				
				return true;
				
			}
		});		
		SymbolFactory.getSymbolFactory().registerSymbolClass(branchB);
		
//		SymbolClass B = new SymbolClass("B", "B");
//		B.addMethod(growthPropagateMethod);
//		SymbolFactory.getSymbolFactory().registerSymbolClass(B);
		
		SymbolClass growthF = new SymbolClass("F","F(grow)");
		growthF.addMethod(growthMethod);
		SymbolFactory.getSymbolFactory().registerSymbolClass(growthF);
		
//		SymbolClass F = new SymbolClass("F");
//		F.addMethod(growthPropagateMethod);
//		SymbolFactory.getSymbolFactory().registerSymbolClass(F);
						
		SymbolClass angleLeft = new SymbolClass("-");
		angleLeft.addMethod(angleMethod);
		SymbolClass angleRight = new SymbolClass("+");
		angleRight.addMethod(angleMethod);
		SymbolFactory.getSymbolFactory().registerSymbolClass(angleLeft);
		SymbolFactory.getSymbolFactory().registerSymbolClass(angleRight);
		
		Symbol axiom = SymbolFactory.getSymbolFactory().createSymbolofClass("B");	
		setAxiom(axiom);	
		addProduction(SimpleParser.parseProduction("B->F[+RSB(branch)][-RSB(branch)][>-RSB(branch)][>+RSB(branch)]B"));
		addProduction(SimpleParser.parseProduction("F->F(grow)"));
		
		initDefaultParameters();
						
	}
	
	public void initDefaultParameters(){
		setDefaultParameter("radius", 0.01f);
		setDefaultParameter("radiusMultiplier", 1.5f);
		setDefaultParameter("distance", 0.2f);
		setDefaultParameter("distanceMultiplier", 1.4f);
		setDefaultParameter("distanceMultiplierBranch", 1.2f);	
		setDefaultParameter("spreadVariation", 0f);
		setDefaultParameter("turnAngle", 90f);
		setDefaultParameter("rollAngle", 90f);
		setDefaultParameter("pitchAngle", 90f);
		setDefaultParameter("branchChance", 0.6f);
		setDefaultParameter("leafSize", 0.3f);
		setDefaultParameter("distanceVariation", 0f);
		setDefaultParameter(Symbol.SCALE_MULTIPLIER, 0.9f);
	}

}
